package com.lineage.server.utils;

import com.lineage.server.datatables.MapsGroupTable;
import com.lineage.server.datatables.MapsTable;
import com.lineage.server.model.Instance.L1DollInstance;
import com.lineage.server.model.Instance.L1EffectInstance;
import com.lineage.server.model.Instance.L1NpcInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.Instance.L1PetInstance;
import com.lineage.server.model.Instance.L1SkinInstance;
import com.lineage.server.model.Instance.L1SummonInstance;
import com.lineage.server.model.L1Clan;
import com.lineage.server.model.L1Location;
import com.lineage.server.model.L1Object;
import com.lineage.server.model.map.L1Map;
import com.lineage.server.model.map.L1WorldMap;
import com.lineage.server.serverpackets.S_CharVisualUpdate;
import com.lineage.server.serverpackets.S_MapID;
import com.lineage.server.serverpackets.S_MapTimer;
import com.lineage.server.serverpackets.S_NPCPack_Doll;
import com.lineage.server.serverpackets.S_NPCPack_Eff;
import com.lineage.server.serverpackets.S_NPCPack_Hierarch;
import com.lineage.server.serverpackets.S_NPCPack_Pet;
import com.lineage.server.serverpackets.S_NPCPack_Skin;
import com.lineage.server.serverpackets.S_NPCPack_Summon;
import com.lineage.server.serverpackets.S_NPCTalkReturn;
import com.lineage.server.serverpackets.S_OtherCharPacks;
import com.lineage.server.serverpackets.S_OwnCharPack;
import com.lineage.server.serverpackets.S_PacketBoxWindShackle;
import com.lineage.server.serverpackets.S_Paralysis;
import com.lineage.server.serverpackets.S_SystemMessage;
import com.lineage.server.serverpackets.ServerBasePacket;
import com.lineage.server.templates.L1MapsLimitTime;
import com.lineage.server.timecontroller.pc.MapTimerThread;
import com.lineage.server.timecontroller.server.ServerUseMapTimer;
import com.lineage.server.types.Point;
import com.lineage.server.world.World;
import com.lineage.server.world.WorldClan;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Teleportation {
  private static final Log _log = LogFactory.getLog(Teleportation.class);
  
  private static Random _random = new Random();
  
  public static void teleportation(L1PcInstance pc) {
    try {
      if (pc == null)
        return; 
      if (pc.getOnlineStatus() == 0)
        return; 
      if (pc.getNetConnection() == null)
        return; 
      if (pc.isDead())
        return; 
      if (pc.isTeleport())
        return; 
      pc.getMap().setPassable((Point)pc.getLocation(), true);
      short mapId = pc.getTeleportMapId();
      if (pc.isDead() && mapId != 9101)
        return; 
      int x = pc.getTeleportX();
      int y = pc.getTeleportY();
      int head = pc.getTeleportHeading();
      short pc_mapId = pc.getMapId();
      L1Map map = L1WorldMap.get().getMap(mapId);
      if (!map.isInMap(x, y) && !pc.isGm()) {
        x = pc.getX();
        y = pc.getY();
        mapId = pc.getMapId();
      } 
      L1Clan clan = WorldClan.get().getClan(pc.getClanname());
      if (clan != null && clan.getWarehouseUsingChar() == pc.getId()) {
        clan.setWarehouseUsingChar(0);
        pc.sendPackets((ServerBasePacket)new S_NPCTalkReturn(pc.getId(), "y_who"));
        pc.sendPackets((ServerBasePacket)new S_NPCTalkReturn(pc.getId(), "y_who"));
      } 
      World.get().moveVisibleObject((L1Object)pc, mapId);
      pc.setLocation(x, y, mapId);
      pc.setHeading(head);
      pc.setOleLocX(x);
      pc.setOleLocY(y);
      boolean isUnderwater = pc.getMap().isUnderwater();
      pc.sendPackets((ServerBasePacket)new S_MapID(pc, pc.getMapId(), isUnderwater));
      if (!pc.isGhost() && !pc.isGmInvis() && !pc.isInvisble())
        pc.broadcastPacketAll((ServerBasePacket)new S_OtherCharPacks(pc)); 
      if (pc.isReserveGhost())
        pc.endGhost(); 
      pc.sendPackets((ServerBasePacket)new S_OwnCharPack(pc));
      pc.removeAllKnownObjects();
      pc.updateObject();
      pc.sendVisualEffectAtTeleport();
      pc.sendPackets((ServerBasePacket)new S_CharVisualUpdate(pc));
      pc.killSkillEffectTimer(32);
      pc.setCallClanId(0);
      HashSet<L1PcInstance> subjects = new HashSet<>();
      subjects.add(pc);
      if (!pc.isGhost()) {
        if (pc.getMap().isTakePets()) {
          Iterator<L1NpcInstance> iterator = pc.getPetList().values().iterator();
          while (iterator.hasNext()) {
            L1NpcInstance petNpc = iterator.next();
            int nx = pc.getX();
            int ny = pc.getY();
            petNpc.set_showId(pc.get_showId());
            teleport(petNpc, nx, ny, mapId, head);
            if (petNpc instanceof L1SummonInstance) {
              L1SummonInstance summon = (L1SummonInstance)petNpc;
              pc.sendPackets((ServerBasePacket)new S_NPCPack_Summon(summon, pc));
            } else if (petNpc instanceof L1PetInstance) {
              L1PetInstance pet = (L1PetInstance)petNpc;
              pc.sendPackets((ServerBasePacket)new S_NPCPack_Pet(pet, pc));
            } 
            Iterator<L1PcInstance> iterator2 = World.get().getVisiblePlayer((L1Object)petNpc).iterator();
            while (iterator2.hasNext()) {
              L1PcInstance visiblePc = iterator2.next();
              visiblePc.removeKnownObject((L1Object)petNpc);
              if (visiblePc.get_showId() == petNpc.get_showId())
                subjects.add(visiblePc); 
            } 
          } 
        } 
        if (!pc.getDolls().isEmpty()) {
          L1Location loc = pc.getLocation().randomLocation(3, false);
          int nx2 = loc.getX();
          int ny2 = loc.getY();
          Object[] dolls = pc.getDolls().values().toArray();
          Object[] array;
          int length = (array = dolls).length;
          int i = 0;
          while (i < length) {
            Object obj = array[i];
            L1DollInstance doll = (L1DollInstance)obj;
            teleport((L1NpcInstance)doll, nx2, ny2, mapId, head);
            pc.sendPackets((ServerBasePacket)new S_NPCPack_Doll(doll, pc));
            doll.set_showId(pc.get_showId());
            Iterator<L1PcInstance> iterator3 = World.get().getVisiblePlayer((L1Object)doll).iterator();
            while (iterator3.hasNext()) {
              L1PcInstance visiblePc2 = iterator3.next();
              visiblePc2.removeKnownObject((L1Object)doll);
              if (visiblePc2.get_showId() == doll.get_showId())
                subjects.add(visiblePc2); 
            } 
            i++;
          } 
        } 
        if (pc_mapId != mapId) {
          L1MapsLimitTime mapsLimitTime = MapsGroupTable.get().findGroupMap(mapId);
          if (mapsLimitTime != null) {
            int order_id = mapsLimitTime.getOrderId();
            int used_time = pc.getMapsTime(order_id);
            int limit_time = mapsLimitTime.getLimitTime();
            if (used_time < limit_time)
              pc.sendPackets((ServerBasePacket)new S_MapTimer(limit_time - used_time)); 
          } 
        } 
        ArrayList<L1EffectInstance> effectlist = pc.get_TrueTargetEffectList();
        Iterator<L1EffectInstance> iterator4 = effectlist.iterator();
        while (iterator4.hasNext()) {
          L1EffectInstance effect = iterator4.next();
          L1Location loc2 = pc.getLocation();
          int nx3 = loc2.getX();
          int ny3 = loc2.getY();
          teleport((L1NpcInstance)effect, nx3, ny3, mapId, head);
          pc.sendPackets((ServerBasePacket)new S_NPCPack_Eff(effect));
          effect.set_showId(pc.get_showId());
          Iterator<L1PcInstance> iterator5 = effect.getKnownPlayers().iterator();
          while (iterator5.hasNext()) {
            L1PcInstance knownPc = iterator5.next();
            knownPc.removeKnownObject((L1Object)effect);
            if (knownPc.get_showId() == effect.get_showId()) {
              knownPc.addKnownObject((L1Object)effect);
              knownPc.sendPackets((ServerBasePacket)new S_NPCPack_Eff(effect));
            } 
          } 
        } 
        if (pc.getSkins() != null) {
          Map<Integer, L1SkinInstance> skinList = pc.getSkins();
          Iterator<Integer> iterator6 = skinList.keySet().iterator();
          while (iterator6.hasNext()) {
            Integer gfxid = iterator6.next();
            L1SkinInstance skin = skinList.get(gfxid);
            teleport((L1NpcInstance)skin, pc.getX(), pc.getY(), pc.getMapId(), pc.getHeading());
            pc.sendPackets((ServerBasePacket)new S_NPCPack_Skin(skin));
            skin.set_showId(pc.get_showId());
            Iterator<L1PcInstance> iterator7 = World.get().getVisiblePlayer((L1Object)skin).iterator();
            while (iterator7.hasNext()) {
              L1PcInstance visiblePc3 = iterator7.next();
              visiblePc3.removeKnownObject((L1Object)skin);
              if (visiblePc3.get_showId() == skin.get_showId())
                subjects.add(visiblePc3); 
            } 
          } 
        } 
        if (pc.getHierarchs() != null) {
          int nx2 = pc.getX();
          int ny2 = pc.getY();
          teleport((L1NpcInstance)pc.getHierarchs(), nx2, ny2, mapId, head);
          pc.sendPackets((ServerBasePacket)new S_NPCPack_Hierarch(pc.getHierarchs()));
          pc.getHierarchs().set_showId(pc.get_showId());
          Iterator<L1PcInstance> iterator8 = World.get().getVisiblePlayer((L1Object)pc.getHierarchs()).iterator();
          while (iterator8.hasNext()) {
            L1PcInstance visiblePc4 = iterator8.next();
            visiblePc4.removeKnownObject((L1Object)pc.getHierarchs());
            if (visiblePc4.get_showId() == pc.getHierarchs().get_showId())
              subjects.add(visiblePc4); 
          } 
        } 
      } 
      Iterator<L1PcInstance> iterator9 = subjects.iterator();
      while (iterator9.hasNext()) {
        L1PcInstance updatePc = iterator9.next();
        updatePc.updateObject();
      } 
      Integer time = (Integer)ServerUseMapTimer.MAP.get(pc);
      if (time != null)
        ServerUseMapTimer.put(pc, time.intValue()); 
      boolean isTimingmap = MapsTable.get().isTimingMap(mapId);
      if (isTimingmap) {
        int maxMapUsetime = MapsTable.get().getMapTime(mapId) * 60;
        int usedtime = pc.getMapUseTime(mapId);
        int leftTime = maxMapUsetime - usedtime;
        MapTimerThread.put(pc, leftTime);
      } else if (MapTimerThread.TIMINGMAP.get(pc) != null) {
        MapTimerThread.TIMINGMAP.remove(pc);
        System.out.println("移出清单");
      } 
      if (pc.getoldMapId() != pc.getMapId()) {
        if (pc.isActived()) {
          pc.setActived(false);
          if (pc.get_fwgj() > 0) {
            pc.setlslocx(0);
            pc.setlslocy(0);
            pc.set_fwgj(0);
          } 
          pc.killSkillEffectTimer(8853);
        } 
        if (pc.getnpcdmg() > 0.0D) {
          pc.sendPackets((ServerBasePacket)new S_SystemMessage("\\fU目前攻击累积伤害:" + pc.getnpcdmg()));
          pc.sendPackets((ServerBasePacket)new S_SystemMessage("\\fU因您更新地图,攻击伤害累积重新计算"));
          pc.setnpcdmg(0.0D);
        } 
        pc.setoldMapId(pc.getMapId());
      } 
      pc.setTeleport(false);
      if (pc.hasSkillEffect(167))
        pc.sendPackets((ServerBasePacket)new S_PacketBoxWindShackle(pc.getId(), pc.getSkillEffectTimeSec(167))); 
      pc.sendPackets((ServerBasePacket)new S_Paralysis(7, false));
      if (!pc.isGmInvis())
        pc.getMap().setPassable((Point)pc.getLocation(), false); 
      pc.getPetModel();
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public static void teleport(L1NpcInstance npc, int x, int y, short map, int head) {
    try {
      World.get().moveVisibleObject((L1Object)npc, map);
      L1WorldMap.get().getMap(npc.getMapId()).setPassable(npc.getX(), npc.getY(), true, 2);
      npc.setX(x);
      npc.setY(y);
      npc.setMap(map);
      npc.setHeading(head);
      L1WorldMap.get().getMap(npc.getMapId()).setPassable(npc.getX(), npc.getY(), false, 2);
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
}
